package edu.unr.cater.npap.web;

import edu.unr.cater.npap.share.domain.File;
import edu.unr.cater.npap.share.domain.Project;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.roo.addon.web.mvc.controller.scaffold.RooWebScaffold;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;

@RequestMapping("/files")
@Controller
@RooWebScaffold(path = "files", formBackingObject = File.class)
public class FileController {

    @RequestMapping(method = RequestMethod.POST, produces = "text/html")
    public String create(@Valid File file, BindingResult bindingResult, @RequestParam(value = "idproject", required = false) Integer idproject, Model uiModel, @RequestParam("content") CommonsMultipartFile content, HttpServletRequest httpServletRequest) {
        System.out.println(new java.io.File(".").getAbsolutePath());
        java.io.File dest = new java.io.File("uploadfiles/" + content.getOriginalFilename());
        System.out.println(dest.getAbsolutePath());
        try {
            content.transferTo(dest);
            file.setFileName(content.getOriginalFilename());
            file.setFilesize(content.getSize());
            file.setFilepath(dest.getAbsolutePath());
            file.setContentType(content.getContentType());
            file.setIdproject(Project.findProject(idproject));
            uiModel.addAttribute("project", Project.findProject(idproject));
            uiModel.addAttribute("projects", Project.findAllProjects());
        } catch (Exception e) {
            e.printStackTrace();
            return "files/create";
        }
        uiModel.addAttribute("project", Project.findProject(idproject));
        uiModel.addAttribute("projects", Project.findAllProjects());
        file.persist();
        return "redirect:/files?idproject=" + idproject;
    }

    @InitBinder
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws ServletException {
        binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
    }

    @RequestMapping(value = "/downloadfiles/{file_name}.{suffix}", method = RequestMethod.GET)
    @ResponseBody
    public FileSystemResource getFile(@PathVariable("file_name") String fileName, @PathVariable("suffix") String fileExtension, HttpServletResponse response) {
        java.io.File file = new java.io.File("uploadfiles/" + fileName + "." + fileExtension);
        System.out.println(file.getAbsolutePath());
        if (!fileExtension.equals(new String("pdf"))) {
            response.addHeader("Content-disposition", "attachment; filename=" + fileName + "." + fileExtension);
        }
        try {
            InputStream is = new FileInputStream(file);
            IOUtils.copy(is, response.getOutputStream());
            response.flushBuffer();
        } catch (IOException ex) {
            throw new RuntimeException("IOError writing file to output stream");
        }
        return null;
    }

    @RequestMapping(params = "form", produces = "text/html")
    public String createForm(@RequestParam(value = "idproject", required = false) Integer idproject, Model uiModel) {
        populateEditForm(uiModel, new File());
        uiModel.addAttribute("project", Project.findProject(idproject));
        uiModel.addAttribute("projects", Project.findAllProjects());
        return "files/create";
    }

    @RequestMapping(value = "/{id}", produces = "text/html")
    public String show(@PathVariable("id") Long id, Model uiModel) {
        uiModel.addAttribute("file", File.findFile(id));
        uiModel.addAttribute("itemId", id);
        return "files/show";
    }

    @RequestMapping(produces = "text/html")
    public String list(@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, @RequestParam(value = "idproject", required = false) Integer idproject, Model uiModel) {
        System.out.println(page);
        System.out.println(size);
        System.out.println(idproject);
        if (page != null || size != null) {
            int sizeNo = size == null ? 10 : size.intValue();
            final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
            uiModel.addAttribute("files", File.findFileEntriesWhere(firstResult, sizeNo, idproject));
            float nrOfPages = (float) File.countFiles() / sizeNo;
            uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
            uiModel.addAttribute("project", Project.findProject(idproject));
            uiModel.addAttribute("projects", Project.findAllProjects());
        } else {
            uiModel.addAttribute("files", File.findAllFiles(Project.findProject(idproject)));
            uiModel.addAttribute("project", Project.findProject(idproject));
            uiModel.addAttribute("projects", Project.findAllProjects());
        }
        return "files/list";
    }

    @RequestMapping(method = RequestMethod.PUT, produces = "text/html")
    public String update(@Valid File file, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
        if (bindingResult.hasErrors()) {
            populateEditForm(uiModel, file);
            return "files/update";
        }
        uiModel.asMap().clear();
        file.merge();
        return "redirect:/files/" + encodeUrlPathSegment(file.getId().toString(), httpServletRequest);
    }

    @RequestMapping(value = "/{id}", params = "form", produces = "text/html")
    public String updateForm(@PathVariable("id") Long id, Model uiModel) {
        populateEditForm(uiModel, File.findFile(id));
        return "files/update";
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = "text/html")
    public String delete(@PathVariable("id") Long id, @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
        File file = File.findFile(id);
        file.remove();
        uiModel.asMap().clear();
        uiModel.addAttribute("page", (page == null) ? "1" : page.toString());
        uiModel.addAttribute("size", (size == null) ? "10" : size.toString());
        return "redirect:/files";
    }

    void populateEditForm(Model uiModel, File file) {
        uiModel.addAttribute("file", file);
        uiModel.addAttribute("projects", Project.findAllProjects());
    }

    String encodeUrlPathSegment(String pathSegment, HttpServletRequest httpServletRequest) {
        String enc = httpServletRequest.getCharacterEncoding();
        if (enc == null) {
            enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
        }
        try {
            pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
        } catch (UnsupportedEncodingException uee) {
        }
        return pathSegment;
    }
}
